perm filename DEFVST.INF[LIB,LSP] blob
sn#577503 filedate 1981-04-09 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00004 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 DEFVST is an acronym for "DEFine a Vector-like STructure"
C00007 00003 The SETVST macro (and SETF) is used in conjunction with DEFVST. The
C00014 00004 CONSTRAINTS, and INITIAL VALUES
C00023 ENDMK
C⊗;
DEFVST is an acronym for "DEFine a Vector-like STructure"
All entries in a Vector-like structure are "pointers" (FIXNUMs, LISTs, etc)
Future plans call for
DEFBST - "DEFine a Bitstring-like STructure", useful where
the structure is an interface to some memory
block required to be sequential by, say, operating
system conventions, or hardware needs.
DEFSTRUCT - "DEFine a general STRUCTure"
which will be done by composing DEFVST and DEFBST.
Vector-like structures are implemented as EXTENDs, which are emulated in
maclisp by HUNKs, and on the LISPMachine by 1-dimensional
ART-Q arrays; EXTENDs interface to a CLASS system, which interface
well be activated at any time when the CLASS system is loaded --
only a skeletal amount of information is necessary in each class
of vector-like structures in order to prepare for the link-up.
Free (global) variables controlling actions:
CONSTRUCTOR-NAMESTRING-PREFIX - constructor name is obtained by
concatenating this string with the
structure name.
SELECTOR-NAMESTRING-STYLE - () ==> selector macro name is same
as keyword (variable name).
- "xxx" ==> selector macro name gotten
by concatenating structure
name, "xxx", and keyword.
Basic macros: DEFVST for defining a structure
SETVST for updating a selected component
(and SETF)
Additional functions:
STRUCT-TYPEP for "structures", returns the given name,
and for non-structures, returns ().
|defvst-construction/||, |defvst-initialize/||, |defvst-typchk/||,
|defvst-construction-1/||, |defvst-selection/||, and |defvst-xref/||
are internal helper functions.
Usage is like:
(DEFVST SHIP
(X-POSITION /: FIXNUM)
Y-POSITION
(MASS = 1000.)
(COST (DAY-HIGH-PRICE))
COLOR )
(SETVST (SHIP-X-POSITION QE2) 109.)
or alternatively,
(SETF (SHIP-X-POSITION QE2) 109.)
since SETF will macroexpand out the component selector, and thus turn
into SETVST, on structures references. Also, a set of "options" may
be specified by including the structure name in a list:
(DEFVST (SHIP <option1> <option2> ...) ...)
currently, only :CONSTRUCTOR and :NO-SELECTOR-MACROS are valid options.
Note that "=" is used as a keyword in the component part to mean
an initialization form follows; and that a component specification
which is just a 2-list is expanded like
(<component-name> <form>) ==> (<component-name> = <form>)
This is done for compatibility of style with the LISPM defstructure.
See further notes below for the meaning of the ":" in the default form.
The SETVST macro (and SETF) is used in conjunction with DEFVST. The
example use of DEFVST "defines" a vector-like structure of 4 components;
the generic name of this structure is "SHIP", and the components are
identified by the ordering of what are called keywords - X-POSITION,
Y-POSITION, MASS, and COLOR. Each "definition" causes the creation of
1) A constructor macro, whose name (normally) is obtained by prefixing
the string "CONS-A-" onto the generic name of the structure.
(Actually, it gets this prefix string from the variable
CONSTRUCTOR-NAMESTRING-PREFIX, so that it can be modified)
In the example, this becomes CONS-A-SHIP. The constructor
permits installing values into the component slots at instantiation
time, which are evaluated from either the (default) forms supplied
by the invocation of DEFVST, or from the forms obtained by keyword
parameters in the instantiating form. E.g.
(CONS-A-BANK DOLLARS (PLUS 300. WALLET) MANAGER '|Jones, J.|)
would put the numerical value of 300.+WALLET in the DOLLARS
component of a newly-created bank, and install |Jones, J.| as
its MANAGER. When the :CONSTRUCTOR option is given, the user
supplies a specific name for this macro.
2) N selector macros, one for each keyword (which denotes one
component slot), which are obtained (normally) by concatenating
the generic name, a "-", and the keyword name. (Actually,
the middle string is obtained from the value of the variable
SELECTOR-NAMESTRING-STYLE, so that it can be modified)
In the example, we have SHIP-X-POSITION, SHIP-Y-POSITION,
SHIP-MASS, and SHIP-COLOR.
2a: (SHIP-X-POSITION QE2)
to obtain the x-coordinate of QE2
2b: (SETVST (SHIP-X-POSITION QE2) 109.)
to change the x-coordinate to of QE2 to 109.
One interesting facet of the selector macroexpansions is that
when done for compilation, the turn into the MacLISP CXR,
which can generally be open-coded in one or two instructions.
But when expanded during interpretation, the go thru a
safety checking function, which assures that a selector
created for a SHIP structure is only applied to SHIP structures,
and not to other kinds of data, or other structures.
When the :NO-SELECTOR-MACROS option is given, then these macros,
like SHIP-X-POSITION, are not created; this is intended to
delete the spurious creation of macros, when another macro
package is using DEFVST like a subroutine.
3) An information structure, stored as the STRUCT=INFO property
of the generic name symbol. This information has the shape
(DEFVST STRUCT=INFO
VERSION-NUMBER
GENERIC-NAME
CONSTRUCTOR-NAME
NUMBER-OF-NAMED-COMPONENTS
COMPONENT-DEFAULT-INITIALIZATION-LISTS
CLASS-SKELETON)
The generic name corresponds to the "name" of the structure
being defined; in the example, it is BANK. The version number
corresponds to a version of "implementation status" for DEFVST --
thus it should be possible to make rather radical changes in
the future implementation, while maintain compatibility with
previously compiled structures (that means that existing FASL
files won't have to be recompiled whenever some change to
DEFVST is made).
The zero'th element of the initializations is either (), or a
3-list of the key-name, selector-name, and default size for the
&REST component - the "block" of unnamed components in the
structure. The remaining elements of the initializations are
the "initialization lists" for each named component:
(<key-name> <corresponding-selector>)
;() initial value, no restrictions
(<key-name> <corresponding-selector> <ini-val-form>)
;no restrictions
(<key-name> <corresponding-selector>
<ini-val-form> . <list-of-types-for-restrictions>)
CONSTRAINTS, and INITIAL VALUES
Each of the components may be constrained to be a particular
type datum, and may be initialized according to the form supplied
as default by the call to DEFVST.
The syntax for a non-simple component specification is a list with
the first element being the key name, the item following the first
"=" in the list being a form which is the default form to be evaluated
for that component in any creations of instances of that structure,
and the element following the first ":" is either a type name or list
of type names that restricts any creating instance from supplying an
initial value of the wrong type. If a key has a restriction
associated with it, but no default initial-value form, then DEFVST
picks some default value consistent with the restriction.
Consider the example
(DEFVST BANK
(DOLLARS : (FIXNUM FLONUM MUMBLE))
MANAGER
(LIMIT : (FIXNUM FLONUM) = 1000000.0)
&REST
VAULTS
30.)
First, the macro invocation of DEFVST would expand into
(EVAL-WHEN (EVAL COMPILE LOAD)
(AND (STATUS FEATURE COMPLR) (SPECIAL BANK-CLASS))
(|defvst-initialize/||
'BANK
'CONS-A-BANK
3
'#((VAULTS BANK-VAULTS 30.)
(DOLLARS BANK-DOLLARS 0 FIXNUM FLONUM MUMBLE)
(MANAGER BANK-MANAGER)
(LIMIT BANK-LIMIT 1000000.0 FIXNUM FLONUM))
1)
(SETF (GET (SI:CLASS-PLIST (GET 'BANK 'CLASS)) ':SOURCE-FILE)
'((AR2 JONL) EXMPL /3))
(DEFPROP BANK-VAULTS (BANK 4 &REST) SELECTOR)
'BANK)
The internal function |defvst-initialize/|| creates the STRUCT=INFO
property for BANK, and sets up macro definitions for all the selector
names, and for the constructor name; also, a "skeleton" is framed
so that all instances may be grouped into a CLASS of such structures.
(This information is kept in in the STRUCT=INFO property.) When the
CLASS system is actually loaded, the skeletons will be fleshed out
to the full degree [ see the documentation on the MacLISP SEND
facility, and on the EXTENDed CLASS system].
After that, then, a "simple" creation instance will take default values
for all components with either initial value or restriction
specifications, and null in the unspecified components; for example
(CONS-A-BANK)
then yields an instance, which when printed as a VECTOR, is like
#( 0 () 1.0E6 () . . . () )
namely, a bank with three named components, and with 30. unnamed
components which are accessed as if VAULTS were a vector name.
Note that the the function CLASS-OF (and also SI:EXTEND-CLASS-OF)
gets the class descriptor for this class of structures, which
may be only a "skeleton" when the CLASS system isn't loaded.
A more complex example of construction, such as,
(CONS-A-BANK DOLLARS (CASEQ VIP
(FEDERAL 15.0E9)
(SAVINGS-&-LOAN 10.0E6)
(MICKEY-MOUSE 1))
MANAGER '|Jones, J.|
LIMIT (BANK-DOLLARS CURRENT-CONSTRUCTION)
VAULTS 12.)
illustrates four points of a creating instance - -
(1) keywords paired with initial values are just alternating
pairs in the list, and
(2) the forms for initial values are substituted into a piece of
code output by the macro, so that they are evaluated at
instantiation time, and
(3) the variable CURRENT-CONSTRUCTION is temporarily bound to the
structure being created so that it may be referenced; the
installing of initial values happens last.
(4) components which are under a restriction, and are not constant
(at compile time) must be submitted to dynamic type checking.
Notice how this macro-expands --
(LET ((CURRENT-CONSTRUCTION (SI:MAKE-EXTEND 33. BANK-CLASS)))
(SETVST (BANK-DOLLARS CURRENT-CONSTRUCTION)
(|defvst-typchk/|| (CASEQ VIP
(FEDERAL 1.5E+10)
(SAVINGS-&-LOAN 10000000.0)
(MICKEY-MOUSE 1))
'(FIXNUM FLONUM MUMBLE)
'BANK-DOLLARS))
(SETVST (BANK-LIMIT CURRENT-CONSTRUCTION)
(|defvst-typchk/|| (BANK-DOLLARS CURRENT-CONSTRUCTION)
'(FIXNUM FLONUM)
'BANK-LIMIT))
CURRENT-CONSTRUCTION)
This code might actually not run, since it could stop on a Restriction
Violation if the variable VIP does not have a value among
FEDERAL, SAVINGS-&-LOAN, MICKEY-MOUSE
for then it would turn up a () for the DOLLARS component, which
was specified to be restricted to fixnums.
Further macro-expansion causes the "SETVST"s to become "SI:XSET"s.
In maclisp, SI:XREF becomes CXR, SI:XSET becomes RPLACX, and
SI:MAKE-EXTEND becomes MAKHUNK (that is how EXTEND's are emulated
there). Neither the EXTEND package nor any runtime CLASS facilities
need be loaded in the runtime environment of code which uses structures,
since dynamic tests are made before any of these facilites are are used
(that is, any facility beyond the MacLISP native HUNK capability).
ββ